﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Wintellect.PowerCollections;
using System.Xml.Linq;
using DbSharp.Framework.Storage.IO;
using DbSharp.Framework.Assertion.Xml;
using System.Diagnostics;

namespace DbSharp.Framework.Diff
{

    public class XmlRecordsetDiff
    {
        #region Private members

        private Bag<XElement> m_ActualSet;
        private Bag<XElement> m_ExpectedSet;
        private Bag<XElement> m_CommonSet;
        private Bag<XElement> m_AddedSet;
        private Bag<XElement> m_DeletedSet;

        #endregion


        #region Private methods
        private void InitCommonSet()
        {
            if (m_CommonSet == null)
                m_CommonSet = m_ActualSet.Intersection(m_ExpectedSet);
        }

        private void InitAddedSet()
        {
            if (m_AddedSet == null)
            {
                if (m_CommonSet == null)
                    InitCommonSet();
                m_AddedSet = m_ActualSet.Difference(m_CommonSet);
            }
        }


        private void InitDeletedSet()
        {
            if (m_DeletedSet == null)
            {
                if (m_CommonSet == null)
                    InitCommonSet();
                m_DeletedSet = m_ExpectedSet.Difference(m_CommonSet);
            }
        }

        #endregion

        public XmlRecordsetDiff(IEnumerable<XElement> actualSet, IEnumerable<XElement> expectedset)
        {
            var comparer = new XElmtRecordEqualityComparer();
            m_ActualSet = new Bag<XElement>(actualSet, comparer);
            m_ExpectedSet = new Bag<XElement>(expectedset, comparer);
        }

        public void ShowAdded(out IList<string> result)
        {
            InitAddedSet();
            var textWriter = new RecordsetXElmtTextWriter(m_AddedSet, false, -1);
            result = textWriter.StringList;
        }



        public void ShowAdded(out IEnumerable<XElement> result)
        {
            InitAddedSet();
            result = m_AddedSet;
        }




        public void ShowDeleted(out IList<string> result)
        {
            InitDeletedSet();
            var textWriter = new RecordsetXElmtTextWriter(m_DeletedSet, false, -1);
            result = textWriter.StringList;
        }



        public void ShowDeleted(out IEnumerable<XElement> result)
        {
            InitDeletedSet();
            result = m_DeletedSet;
        }




        public void ShowCommon(out IList<string> result)
        {
            InitCommonSet();
            var textWriter = new RecordsetXElmtTextWriter(m_CommonSet, false, -1);
            result = textWriter.StringList;
        }

        public void ShowCommon(out IEnumerable<XElement> result)
        {
            InitCommonSet();
            result = m_CommonSet;
        }

        public void ShowChanged(out IList<string> addedLines, out IList<string> deletedLines)
        {
            ShowAdded(out addedLines);
            ShowDeleted(out deletedLines);
        }


        public void ShowChanged(out IEnumerable<XElement> addedLines, out IEnumerable<XElement> deletedLines)
        {
            ShowAdded(out addedLines);
            ShowDeleted(out deletedLines);
        }


        public void ShowSuperSet(out IList<string> addedLines, out IList<string> deletedLines, IList<string> commonLines)
        {
            ShowAdded(out addedLines);
            ShowDeleted(out deletedLines);
            ShowCommon(out commonLines);
        }


        public void ShowSuperSet(out IEnumerable<XElement> addedLines, out IEnumerable<XElement> deletedLines, IEnumerable<XElement> commonLines)
        {
            ShowAdded(out addedLines);
            ShowDeleted(out deletedLines);
            ShowCommon(out commonLines);
        }

    }


}
